package message

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/v2/container/gvar"
	"home-butler/internal/consts"
	"home-butler/internal/model"
	"home-butler/internal/service"
	"home-butler/pkg/taos"
	"home-butler/utility"
	"log"
	"strconv"
	"strings"
	"time"
)

func init() {
	service.RegisterMessage(New())
}

type sMessage struct{}

func New() service.IMessage {
	return &sMessage{}
}

func (s sMessage) MessageParsing(ctx context.Context, req *model.MessageReq) (err error) {
	device, err := service.Device().FindDevice(ctx, req.ClientId)
	_, deviceType, metadata, err := service.Product().FindGetMetadata(ctx, device.ProductId)
	result := utility.Parsing(req.Payload)
	messageService := MessageService{}
	switch deviceType {
	case "gateway":
		messageService.SetStrategy(&MessageStrategyGateway{})
		messageService.CalculateStrategy(ctx, metadata, &result)
		break
	case "device":
		messageService.SetStrategy(&MessageStrategyDevice{})
		messageService.CalculateStrategy(ctx, metadata, &result)
		break
	case "childGatewayDevice":
		break
	default:
		break
	}
	var iden string
	for _, v := range metadata.Properties {
		iden = v.Identifier
	}
	fmt.Println(result[iden].String())
	if deviceType == "gateway" {
		childDevice, err := service.Device().FindDevice(ctx, result[iden].String())
		if err != nil {
			panic(err)
		}
		key, _, cMetadata, err := service.Product().FindGetMetadata(ctx, childDevice.ProductId)
		mes := make(map[string]*gvar.Var)
		columns := make([]string, 0)
		values := make([]string, 0)
		columns = append(columns, "ts")
		values = append(values, strconv.Itoa(int(time.Now().UnixMilli())))
		for _, v := range cMetadata.Properties {
			mes[v.Identifier] = result[v.Identifier]
			if result[v.Identifier] != nil {
				columns = append(columns, v.Identifier)
				values = append(values, result[v.Identifier].String())
			}
		}
		log.Print(mes)
		stableName := consts.TDB_TABLE_NAME_PREFIX + key
		tableName := consts.TDB_TABLE_NAME_PREFIX + key + "_" + result[iden].String()
		sql := fmt.Sprintf("INSERT INTO %s(%s) USING %s TAGS(%s) VALUES(%s)", tableName, strings.Join(columns, ","), stableName, result[iden].String(), strings.Join(values, ","))

		fmt.Println(sql)
		db, err := taos.DB()
		db.CreateTable(sql)
	}

	return
}

// 抽象策略接口
type MessageStrategy interface {
	Calculate(ctx context.Context, metadata *model.ProductMetadataModel, result *map[string]*gvar.Var)
}

// 具体策略A
type MessageStrategyGateway struct{}

func (d *MessageStrategyGateway) Calculate(ctx context.Context, metadata *model.ProductMetadataModel, result *map[string]*gvar.Var) {
	var iden string
	for _, v := range metadata.Properties {
		iden = v.Identifier
	}
	childDevice, err := service.Device().FindDevice(ctx, (*result)[iden].String())
	if err != nil {
		panic(err)
	}
	_, _, cMetadata, err := service.Product().FindGetMetadata(ctx, childDevice.ProductId)
	messageService := MessageService{}
	messageService.SetStrategy(&MessageStrategyDevice{})
	messageService.CalculateStrategy(ctx, cMetadata, result)
}

// 具体策略B
type MessageStrategyDevice struct{}

func (d *MessageStrategyDevice) Calculate(ctx context.Context, metadata *model.ProductMetadataModel, result *map[string]*gvar.Var) {
	mes := make(map[string]*gvar.Var)
	for _, v := range metadata.Properties {
		mes[v.Identifier] = (*result)[v.Identifier]
	}
	j, err := json.Marshal(mes)
	if err != nil {
		panic(err)
	}
	log.Println(string(j))
}

// 具体环境
type MessageService struct {
	strategy MessageStrategy
}

func (s *MessageService) SetStrategy(strategy MessageStrategy) {
	s.strategy = strategy
}

func (s *MessageService) CalculateStrategy(ctx context.Context, metadata *model.ProductMetadataModel, result *map[string]*gvar.Var) {
	s.strategy.Calculate(ctx, metadata, result)
}
